﻿using AutoMapper;
using BCGM.MedicalWisdom.Common.AliYun;
using BCGM.MedicalWisdom.Common.RedisCache;
using BCGM.MedicalWisdom.IServices;
using BCGM.MedicalWisdom.Model;
using BCGM.MedicalWisdom.Model.DTO;
using BCGM.MedicalWisdom.Model.Models;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using System;
using System.Linq.Expressions;
using System.Threading.Tasks;

namespace BCGM.MedicalWisdom.Api.Controllers
{
    /// <summary>
    /// 秒杀活动
    /// </summary>
	[Route("api/[controller]/[action]")]
    [ApiController]
    //[Authorize(Permissions.Name)]
    public class SckillIdActivityController : ControllerBase
    {

        private static readonly object objLock = new object();

        /// <summary>
        /// 服务器接口，因为是模板生成，所以首字母是大写的，自己可以重构下
        /// </summary>
        private readonly ISckillIdActivityServices _sckillIdActivityServices;
        private readonly IMapper _mapper;   //AutoMapper接口需要依赖注入
        private readonly IRedisCacheManager _redisCacheManager;

        private AliYunOSSHelper _oSSHelper;

        public SckillIdActivityController(ISckillIdActivityServices SckillIdActivityServices, IMapper mapper, IRedisCacheManager redisCacheManager, AliYunOSSHelper oSSHelper)
        {
            _sckillIdActivityServices = SckillIdActivityServices;
            _mapper = mapper;
            _redisCacheManager = redisCacheManager;
            _oSSHelper = oSSHelper;
        }

        /// <summary>
        /// 秒杀列表显示
        /// </summary>
        /// <param name="page"></param>
        /// <param name="key"></param>
        /// <param name="intPageSize"></param>
        /// <returns></returns>
        [HttpGet]
        public async Task<MessageModel<PageModel<SckillIdActivity>>> Get(int page = 1, string key = "", int intPageSize = 50)
        {
            if (string.IsNullOrEmpty(key) || string.IsNullOrWhiteSpace(key))
            {
                key = "";
            }

            Expression<Func<SckillIdActivity, bool>> whereExpression = a => a.SeckillName.Contains(key) && a.IsDelete == false;

            return new MessageModel<PageModel<SckillIdActivity>>()
            {
                msg = "获取成功",
                success = true,
                response = await _sckillIdActivityServices.QueryPage(whereExpression, page, intPageSize)
            };

        }
        /// <summary>
        /// 非秒杀商品显示
        /// </summary>
        /// <param name="page"></param>
        /// <param name="key"></param>
        /// <param name="intPageSize"></param>
        /// <returns></returns>
        [HttpGet]
        public async Task<MessageModel<PageModel<GoodsDTO>>> GetnoSckillGoods(int Sid = -1, string goodsName = "", int classifyId = -1, int page = 1, int intPageSize = 50)
        {
            if (Sid == -1)
            {
                return new MessageModel<PageModel<GoodsDTO>>()
                {
                    status = 400,
                    msg = "获取失败",
                    success = false
                };
            }
            return new MessageModel<PageModel<GoodsDTO>>()
            {
                msg = "获取成功",
                success = true,
                response = await _sckillIdActivityServices.GetnoSckillGoods(Sid, goodsName, classifyId, page, intPageSize)
            };

        }
        /// <summary>
        /// 商品类型
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public async Task<List<pharmaceuticalsfen>> GetGoodType()
        {
            return await _sckillIdActivityServices.GetGoodType();
        }
        /// <summary>
        /// 添加秒杀活动商品
        /// </summary>
        /// <param name="sckillGoodsIds"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<MessageModel<string>> AddSckillGoods(SckillGoodsDTO sckillGoodsIds)
        {
            var data = new MessageModel<string>();

            var id = await _sckillIdActivityServices.AddSckillGoods(sckillGoodsIds);
            data.success = id > 0;
            if (data.success)
            {
                data.response = id.ObjToString();
                data.msg = "添加成功";
            }

            return data;
        }


        /// <summary>
        /// 根据Id搜索秒杀活动
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpGet("{id}")]
        public async Task<MessageModel<SckillIdActivity>> GetSckillById(string id)
        {
            return new MessageModel<SckillIdActivity>()
            {
                msg = "获取成功",
                success = true,
                response = await _sckillIdActivityServices.QueryById(id)
            };
        }
        /// <summary>
        /// 添加秒杀活动
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<MessageModel<string>> AddSckill(SckillDTO request)
        {
            var data = new MessageModel<string>();

            SckillIdActivity sckills = _mapper.Map<SckillIdActivity>(request);
            var id = await _sckillIdActivityServices.Add(sckills);
            data.success = id > 0;
            if (data.success)
            {
                data.response = id.ObjToString();
                data.msg = "添加成功";
            }

            return data;
        }
        /// <summary>
        /// 修改秒杀活动
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [HttpPut]
        public async Task<MessageModel<string>> UpdateSckill(SckillIdActivity request)
        {
            var data = new MessageModel<string>();
            data.success = await _sckillIdActivityServices.Update(request);
            if (data.success)
            {
                data.msg = "更新成功";
                data.response = request?.SckillId.ObjToString();
            }

            return data;
        }
        /// <summary>
        /// 删除秒杀活动（逻辑删）
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpDelete]
        public async Task<MessageModel<string>> DeleteSckill(int id)
        {
            var data = new MessageModel<string>();
            var model = await _sckillIdActivityServices.QueryById(id);
            model.IsDelete = true;
            data.success = await _sckillIdActivityServices.Update(model);
            if (data.success)
            {
                data.msg = "删除成功";
                data.response = model?.SckillId.ObjToString();
            }

            return data;
        }
        /// <summary>
        /// 获取待预热的秒杀活动商品信息
        /// </summary>
        /// <param name="seckillId"></param>
        /// <returns></returns>
        [HttpGet]
        public async void GetSeckillGoods(int seckillId)
        {
            //await _sckillIdActivityServices.GetSeckillGoods(seckillId);
            string key = "SeckillGoodsInfo";
            List<SeckillGoodMessage> seckillGoodMessages = await _sckillIdActivityServices.GetSeckillGoods(seckillId);
            string seckillGoodsInfo = JsonConvert.SerializeObject(seckillGoodMessages);
            _redisCacheManager.HSet(key, "双11", seckillGoodsInfo);
        }

        /// <summary>
        /// 获取秒杀商品列表（根据审批状态分类）
        /// </summary>
        /// <param name="Sid"></param>
        /// <param name="goodsName"></param>
        /// <param name="classifyId"></param>
        /// <param name="page"></param>
        /// <param name="intPageSize"></param>
        /// <returns></returns>
        [HttpGet("GetSckillGoods")]
        public async Task<MessageModel<PageModel<SeckillGoodMessage>>> GetSckillGoods(int goodStatus = -1, int page = 1, int intPageSize = 50)
        {
            return new MessageModel<PageModel<SeckillGoodMessage>>()
            {
                msg = "获取成功",
                success = true,
                response = await _sckillIdActivityServices.GetSckillGoods(goodStatus, page, intPageSize)
            };

        }
        /// <summary>
        /// 获取Redis中缓存秒杀商品信息
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        [HttpGet]
        public async Task<MessageModel<List<SeckillGoodMessage>>> GetSeckillGood()
        {
            string key = "SeckillGoodsInfo";
            string seckillgoods = _redisCacheManager.HGetValue(key, "双11");
            return new MessageModel<List<SeckillGoodMessage>>()
            {
                msg = "获取成功",
                success = true,
                response = JsonConvert.DeserializeObject<List<SeckillGoodMessage>>(seckillgoods)
            };
        }
        /// <summary>
        /// Redis加锁
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public async Task<MessageModel<List<SeckillGoodMessage>>> GetRedisLock()
        {
            var data = new MessageModel<List<SeckillGoodMessage>>();
            string key = "SeckillGoodsInfo";
            string value = "";
            if (!_redisCacheManager.Get(key))
            {
                lock (objLock)
                {
                    //value = _redisCacheManager.GetValue(key);
                    Console.WriteLine("Time:" + DateTime.Now);
                    Thread.Sleep(2000);
                }
            }
            Thread.Sleep(2000);
            value = _redisCacheManager.HGetValue(key, "双11");
            if (value.IsNotEmptyOrNull())
            {
                data.success = true;
                data.msg = "获取成功";
                data.response = JsonConvert.DeserializeObject<List<SeckillGoodMessage>>(value);
            }
            else
            {
                data.success = false;
                data.msg = "获取失败";
                data.response = JsonConvert.DeserializeObject<List<SeckillGoodMessage>>(value);
            }

            //string seckillgoods = _redisCacheManager.HGetValue(key, "双11");


            return data;
        }
        /// <summary>
        /// RedisLock锁测试
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public void RedisLock()
        {
            //for (int i = 0; i < 10; i++)
            //{
            //    Console.WriteLine("RedisLockTime:" + DateTime.Now);
            //    GetLock();
            //    GetLock2();
            //}
            TestLock testlock = new TestLock();
            Thread th = new Thread(() =>
            {
                //模拟死锁：造成死锁，使lock无法释放，在i=5时，跳出死循环，释放lock
                testlock.DoWorkWithLock();
            });
            th.Start();
            Thread.Sleep(1000);
            Thread th2 = new Thread(() =>
            {              
                //这个地方你可能会有疑惑，但存在这种情况，比如你封装的dll，对其它开发人员不是可见的
                //开发人员很有可能在他的逻辑中，加上一个lock保证方法同时被一个线程调用，但这时有其它的线程正在调用该方法，
                //但并没有释放，死锁了，那么在这里就不会被执行，除非上面的线程释放了lock锁定的对象。这里的lock也可以理解为一个标识，线程1被锁定的对象
                //是否已经被释放，
                //如果没有释放，则无法继续访问lock块中的代码。
                lock (testlock)
                {
                    // 如果该对象中lock(this)不释放（testlock与this指的是同一个对象），则其它线程如果调用该方法，则会出现直到lock(this)释放后才能继续调。  
                    testlock.MotherCallYouDinner();
                    testlock.DoWorkWithLock();
                }
            });
            th2.Start();

        }
        //private void GetLock()
        //{
        //    lock (objLock)
        //    {
        //        //value = _redisCacheManager.GetValue(key);
        //        //       Console.WriteLine("GetLock");
        //        //       Console.WriteLine("Time:" + DateTime.Now);
        //        //       Thread.Sleep(5000);
        //        //   lock (objLock)
        //        //{
        //        Console.WriteLine("lock this");
        //        int i = 0;
        //        while (true)
        //        {
        //            Console.WriteLine("At work, do not disturb...,Thread id is " + Thread.CurrentThread.ManagedThreadId.ToString());
        //            Thread.Sleep(1000);
        //            if (i == 5)
        //            {
        //                break;
        //            }
        //            Console.WriteLine(i.ToString());
        //            i++;
        //        }
        //        Console.WriteLine("lock dispose");
        //    }
        //}
        //private void GetLock2()
        //{
        //    Console.WriteLine("Your mother call you to home for dinner.");
        //}

        /// <summary>
        /// 批量添加图片（AliYun图片管理OSS）
        /// </summary>
        /// <param name="files"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<ActionResult> UploadPic(List<IFormFile> files)
        {
            //15M
            var maxRequestLength = 1024 * 1024 * 15;
            List<string> filesName = new List<string>();
            if (files.Count == 0) return Content("NoFile", "text/html");
            else
            {
                //List<AliyunUploadModel> fileList = new List<AliyunUploadModel>();

                for (var i = 0; i < files.Count; i++)
                {
                    var file = files[i];
                    if (null == file || file.Length <= 0) return Content("格式不正确！", "text/html");
                    if (file.Length > maxRequestLength)
                    {
                        return Content("文件大小超出限制！", "text/html");
                    }

                    var fname = DateTime.Now.ToString("yyyyMMddHHmmssffffff") + i + Path.GetExtension(file.FileName);

                    //if (!FileExtensionFun.CheckImageFileType(fname))
                    //{
                    //    return Content("上传的图片格式不正确", "text/html");
                    //}

                }
                filesName = await _oSSHelper.AliYunUpLoad(files);

            }
            return Content(string.Join(",", filesName), "text/html");
        }

    }

    class TestLock
     {
         public static readonly object objLock = new object();
         /// <summary>
         ///  该方法，希望某人在工作的时候，其它人不要打扰（希望只有一个线程在执行)
         /// </summary>
         /// <param name="methodIndex"></param>
         public void DoWorkWithLock()
         {
             //锁当前对象
             lock (this)
             {
                 Console.WriteLine("lock this");
                 int i = 0;
                 while (true)
                 {
                     Console.WriteLine("At work, do not disturb...,Thread id is " + Thread.CurrentThread.ManagedThreadId.ToString());
                    Console.WriteLine("DoWorkWithLockTime:" + DateTime.Now);
                    Thread.Sleep(1000);
                     if (i == 5)
                     {
                         break;
                     }
                     Console.WriteLine(i.ToString());
                     i++;
                 }
             }
             Console.WriteLine("lock dispose");
         }
         public void MotherCallYouDinner()
         {
             Console.WriteLine("Your mother call you to home for dinner.");
            Console.WriteLine("MotherCallYouDinnerTime:" + DateTime.Now);
        }
     }
}